#! /usr/bin/env python

import json
import threading
import socket
import hashlib
import random
from datetime import datetime

ffshare_version = '1.2.0'
ffshare_cmds = ['#send', '#recv']
g_debug = False

g_code = {
    'await': 200,
    'go': 201,
}

def debug(*args, **kwargs):
    if g_debug:
        print(*args, **kwargs)

def timestamp():
    return datetime.now().strftime('%Y-%m-%d_%H:%M:%S')

def task_transfer(session_send, session_recv):
    print('do transfer')
    pass

def handshake(client_socket):
    def get_token():
        time = datetime.now()
        time_str = time.strftime('%Y-%m-%d_%H:%M:%S_%f_')
        rand = random.randint(0, 65535)
        rand_str = time_str + f'{rand}'
        sha1 = hashlib.sha1()
        sha1.update(rand_str.encode('utf-8'))
        return sha1.hexdigest()

    def get_key(token):
        SALT = '18df1c9e79dbf27b1008a5f25c4d4213cb90b44c'
        sha1 = hashlib.sha1()
        sha1.update((token + SALT).encode('utf-8'))
        return sha1.hexdigest()

    # STEP 1: send token to client
    token = get_token()
    key = get_key(token)
    client_socket.send(token.encode('utf-8'))

    # STEP 2: recv client's req
    data = client_socket.recv(1024)
    if not data:
        client_socket.close()
        return None

    # STEP 3: check key
    rsp = json.loads(data.decode('utf-8'))
    if rsp['key'] != key:
        return None

    if rsp['ver'] != ffshare_version:
        return None
    
    if rsp['cmd'] not in ffshare_cmds:
        return None

    if not rsp['name']:
        return None
    
    return rsp


def start_tcp_server(host='127.0.0.1', port=12345):
    # create TCP socket
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # bind server addr and port.
    server_socket.bind((host, port))
    # listen client，max 5 connections on queue
    server_socket.listen(5)
    print(f"server listen {host}:{port}...")

    # global client for transfer match
    session_await = None

    while True:
        # step 1: wait client connection
        client_socket, client_address = server_socket.accept()
        
        debug(f'connect client: {client_address}')

        # step 2: handshake
        rsp = handshake(client_socket)
        if not rsp:
            client_socket.close()
            continue
        
        session = {}
        session['sock'] = client_socket
        session['addr'] = client_address
        session['name'] = rsp['name']
        session['cmd'] = rsp['cmd']
        session['time'] = timestamp()
        print(session)

        if not session_await:
            session_await = session
            session = None
            # TODO: send wait
            continue
        else:
            if session_await['cmd'] != session['cmd']:
                task_transfer(session_await, session)
                #start transfer
                pass
            else:
                # send session has taken
                pass
            pass

if __name__ == '__main__':
    start_tcp_server()
    pass
